#ifndef KLIB_H
#define KLIB_H

#include "comm/types.h"
#include <stdarg.h>

void kernel_strcpy(char *dest, const char *src);
void kernel_strncpy(char *dest, const char *src, int size);
int kernel_strncmp(const char *s1, const char *s2, int size);
int kernel_strlen(const char *str);

void kernel_memcpy(void *dest, void *src, int size);
void kernel_memset(void *dest, uint8_t v, int size);
int kernel_memcmp(void *d1, void *d2, int size);

void kernel_vsprintf(char *strbuf, const char *format, va_list args);
void kernel_sprintf(char *strbuf, const char *format, ...);
void kernel_itoa(char *buf, int num, int base);

/**
 * 向下对齐
 */
static inline uint32_t down2(uint32_t size, uint32_t bound)
{
    // 设size = 0x1010, bound = 0x1000
    // bound - 1 = 0x0FFF
    // ~(bound - 1) = 0xF000
    // size & ~(bound - 1) = 0x1000
    return size & ~(bound - 1);
}

/**
 * 向上对齐
 */
static inline uint32_t up2(uint32_t size, uint32_t bound)
{
    // 设size = 0x1010, bound = 0x1000
    // (size + bound - 1) = 0x1010 + 0x1000 - 1 = 0x2010 - 1 = 0x200F
    // ~(bound - 1) = 0xF000
    // (size + bound - 1) & ~(bound - 1) = 0x200F & 0xF000 = 0x2000
    return (size + bound - 1) & ~(bound - 1);
}

#ifndef RELEASE

#define ASSERT(expr) \
    if (!(expr)) pannic(__FILE__, __LINE__, __func__, #expr)

void pannic(const char *file, int line, const char *func, const char *cond);

#else   // RELEASE
#define ASSERT(expr) ((void)0)
#endif  // RELEASE

#endif  // KLIB_H
